﻿class Plane3D extends MovieClip {
	private var words:Array;
	
	private var vpX:Number = Stage.width/2;
	private var vpY:Number = Stage.height/2;
	
	private var angleX:Number = 0;
	private var angleY:Number = 0;
	
	public function Plane3D() {
		init();
		onEnterFrame = loop;
		Key.addListener({onKeyDown:mx.utils.Delegate.create(this, keyDownHandler)});
	}
	
	private function init():Void {
		words = new Array();
		var points:Array;
		
		points = new Array();
		points.push({p3d:new Point3D(-150, -250, 100), mc:getBall()});
		points.push({p3d:new Point3D(150, -250, 100), mc:getBall()});
		points.push({p3d:new Point3D(150, -150, 100), mc:getBall()});
		points.push({p3d:new Point3D(-50, -150, 100), mc:getBall()});
		points.push({p3d:new Point3D(-50, -50, 100), mc:getBall()});
		points.push({p3d:new Point3D(50, -50, 100), mc:getBall()});
		points.push({p3d:new Point3D(50, 50, 100), mc:getBall()});
		points.push({p3d:new Point3D(-50, 50, 100), mc:getBall()});
		points.push({p3d:new Point3D(-50, 150, 100), mc:getBall()});
		points.push({p3d:new Point3D(150, 150, 100), mc:getBall()});
		points.push({p3d:new Point3D(150, 250, 100), mc:getBall()});
		points.push({p3d:new Point3D(-150, 250, 100), mc:getBall()});
		for(var i:Number=0; i<points.length; i++){
			points[i].p3d.setVanishingPoint(vpX, vpY);
			points[i].p3d.setCenter(0, 0, 200);
		}		
		words.push(points);

		updateBalls();
	}
	
	private function getBall():MovieClip{
		var size:Number = 10;
		var depth:Number = this.getNextHighestDepth();
		var ball_mc:MovieClip = this.createEmptyMovieClip("ball" + depth, depth);
		ball_mc.lineStyle(1, 0x000000, 100);
		var curveCount:Number = 16;
		var dAngle:Number = (2*Math.PI)/curveCount;
		var dCos:Number = Math.cos(dAngle);
		var dSin:Number = Math.sin(dAngle);
		var dAngle2:Number = dAngle/2;
		var dCos2:Number = Math.cos(dAngle2);
		var dSin2:Number = Math.sin(dAngle2);
		var x1:Number = size/2;
		var y1:Number = 0;
		ball_mc.moveTo(x1, y1);
		ball_mc.beginFill(0xff0000, 100);
		for (var i:Number = 0; i<curveCount; i++) {
			var x2:Number = dCos*x1-dSin*y1;
			var y2:Number = dCos*y1+dSin*x1;
			var xCon:Number = dCos2*x1-dSin2*y1;
			var yCon:Number = dCos2*y1+dSin2*x1;
			ball_mc.curveTo(xCon, yCon, x2, y2);
			x1 = x2;
			y1 = y2;
		}
		ball_mc.endFill();
		return ball_mc;		
	}
	
	private function updateBalls():Void{
		for(var j:Number=0; j<words.length; j++){
			for(var i:Number=0; i<words[j].length; i++){
				if(words[j][i].p3d.screenX>=0&&words[j][i].p3d.screenX<=Stage.width
					&&words[j][i].p3d.screenY>=0&&words[j][i].p3d.screenY<=Stage.height){
					words[j][i].mc._visible = true;
					words[j][i].mc._x = words[j][i].p3d.screenX;
					words[j][i].mc._y = words[j][i].p3d.screenY;
					words[j][i].mc._alpha = words[j][i].p3d.scale * 100;
					words[j][i].mc._xscale = words[j][i].mc._yscale = words[j][i].p3d.scale * 100;
				}else{
					words[j][i].mc._visible = false;
				}
			}
		}
	}
	
	private function loop():Void{
		angleX *= .9;
		angleY *= .9;
		
		for(var j:Number=0; j<words.length; j++){
			for(var i:Number=0; i<words[j].length; i++){
				words[j][i].p3d.rotateX(angleX);
				words[j][i].p3d.rotateY(angleY);
			}
		}

		this.clear();
		this.lineStyle(0);
		
		for(var j:Number=0; j<words.length; j++){
			this.moveTo(words[j][0].p3d.screenX, words[j][0].p3d.screenY);
			for(var i:Number=1; i<words[j].length; i++){
				this.lineTo(words[j][i].p3d.screenX, words[j][i].p3d.screenY);
			}
			this.lineTo(words[j][0].p3d.screenX, words[j][0].p3d.screenY);
		}
		
		updateBalls();
	}
	
	private function keyDownHandler():Void{
		switch(Key.getCode()){
			case Key.UP:
				angleX -= 0.1;
				break;
			case Key.DOWN:
				angleX += 0.1;
				break;
			case Key.LEFT:
				angleY -= 0.1;
				break;
			case Key.RIGHT:
				angleY += 0.1;
				break;
		}
	}
}
